{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "49a34681",
   "metadata": {},
   "source": [
    "- 手写数字的MNIST数据库：http://yann.lecun.com/exdb/mnist/\n",
    "- 简单数据格式：http://pjreddie.com/projects/mnist-in-csv/\n",
    "- 训练集http://www.pjreddie.com/media/files/mnist_train.csv\n",
    "- 测试集http://www.pjreddie.com/media/files/mnist_test.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "554edcd1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 引入相关包\n",
    "import numpy\n",
    "import scipy.special\n",
    "import matplotlib.pyplot\n",
    "\n",
    "# 定义神经网络\n",
    "class NeuralNetwork:\n",
    "    # 初始化神经网络\n",
    "    def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):\n",
    "        # 设置输入层 隐层 输出层数量\n",
    "        self.inodes = inputnodes\n",
    "        self.hnodes = hiddennodes\n",
    "        self.onodes = outputnodes\n",
    "        \n",
    "        # 设置权重\n",
    "        self.wih = numpy.random.normal(0.0,pow(self.hnodes,-0.5),(self.hnodes, self.inodes))\n",
    "        self.who = numpy.random.normal(0.0,pow(self.onodes, -0.5),(self.onodes, self.hnodes))\n",
    "        \n",
    "        # 设置学习率\n",
    "        self.lr = learningrate\n",
    "        \n",
    "        # 激活函数\n",
    "        self.activation_function = lambda x: scipy.special.expit(x)\n",
    "        \n",
    "        pass\n",
    "    \n",
    "    # 训练神经网络\n",
    "    def train(self, inputs_list, targets_list):\n",
    "        # 转化为二维数组\n",
    "        inputs = numpy.array(inputs_list, ndmin=2).T\n",
    "        targets = numpy.array(targets_list, ndmin=2).T\n",
    "        \n",
    "        # 隐藏层计算\n",
    "        hidden_inputs = numpy.dot(self.wih, inputs)\n",
    "        hidden_outputs = self.activation_function(hidden_inputs)\n",
    "        # 输出层计算\n",
    "        final_inputs = numpy.dot(self.who, hidden_outputs)\n",
    "        final_outputs = self.activation_function(final_inputs)\n",
    "        \n",
    "        # 计算误差\n",
    "        output_errors = targets - final_outputs\n",
    "        \n",
    "        # 权重分隔误差\n",
    "        hidden_errors = numpy.dot(self.who.T, output_errors)\n",
    "        \n",
    "        # 更新隐藏层到输出层权重\n",
    "        self.who +=self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))\n",
    "        \n",
    "        # 更新输入层到隐藏层权重\n",
    "        self.wih +=self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))\n",
    "        pass\n",
    "    \n",
    "    # 查询结果\n",
    "    def query(self,inputs_list):\n",
    "        # 将输入转换为二维数组\n",
    "        inputs = numpy.array(inputs_list, ndmin=2).T\n",
    "        # 隐藏层计算\n",
    "        hidden_inputs = numpy.dot(self.wih, inputs)\n",
    "        hidden_outputs = self.activation_function(hidden_inputs)\n",
    "        # 输出层计算\n",
    "        final_inputs = numpy.dot(self.who, hidden_outputs)\n",
    "        final_outputs = self.activation_function(final_inputs)\n",
    "        return final_outputs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a1019101",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 设置入参\n",
    "input_nodes = 784\n",
    "# 隐层数量 200最佳值\n",
    "hidden_nodes = 100\n",
    "output_nodes = 10\n",
    "# 学习率 0.2最佳值\n",
    "learning_rate = 0.3\n",
    "\n",
    "# 创建神经网络\n",
    "n = NeuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)\n",
    "# 输出\n",
    "#n.query([1.0, 0.5, -1.5])\n",
    "\n",
    "# 加载训练数据集\n",
    "\n",
    "# 100训练数据集 准确率0.6\n",
    "#training_data_file = open(\"mnist_dataset/mnist_train_100.csv\",'r')\n",
    "# 60000训练数据集 准确率0.9448\n",
    "training_data_file = open(\"mnist_dataset/mnist_train.csv\",'r')\n",
    "training_data_list = training_data_file.readlines()\n",
    "training_data_file.close()\n",
    "\n",
    "# 神经网络训练 训练5次左右效果更佳\n",
    "for record in training_data_list:\n",
    "    all_values = record.split(',')\n",
    "    inputs = (numpy.asfarray(all_values[1:])/255.0 * 0.99) + 0.01\n",
    "    targets = numpy.zeros(output_nodes) + 0.01\n",
    "    targets[int(all_values[0])] = 0.99\n",
    "    n.train(inputs, targets)\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c347ae51",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试网络\n",
    "\n",
    "# 10条测试数据 准确率0.6\n",
    "#test_data_file = open(\"mnist_dataset/mnist_test_10.csv\", 'r')\n",
    "# 1000条测试数据 准确率0.9448\n",
    "test_data_file = open(\"mnist_dataset/mnist_test.csv\", 'r')\n",
    "test_data_list = test_data_file.readlines()\n",
    "test_data_file.close()\n",
    "test_all_vlaues = test_data_list[0].split(',')\n",
    "print(test_all_vlaues[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "889e111d",
   "metadata": {},
   "outputs": [],
   "source": [
    "image_array = numpy.asfarray(test_all_vlaues[1:]).reshape((28,28))\n",
    "matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ba65cf3",
   "metadata": {},
   "outputs": [],
   "source": [
    "n.query((numpy.asfarray(test_all_vlaues[1:])/255.0 * 0.99) + 0.01)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d646d8bf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 计算得分\n",
    "scorecard = []\n",
    "for record in test_data_list:\n",
    "    values = record.split(',')\n",
    "    correct_label = int(values[0])\n",
    "    print(correct_label, \"correct_label\")\n",
    "    inputs = (numpy.asfarray(values[1:])/255.0 * 0.99)+0.01\n",
    "    outputs = n.query(inputs)\n",
    "    label = numpy.argmax(outputs)\n",
    "    print(label, \"networks's anser\")\n",
    "    if(label == correct_label):\n",
    "        scorecard.append(1)\n",
    "    else:\n",
    "        scorecard.append(0)\n",
    "        pass\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c636b264",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(scorecard)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7c4aed19",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 计算准确率\n",
    "scorecard_array = numpy.asarray(scorecard)\n",
    "print(\"performance = \", scorecard_array.sum()/scorecard_array.size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0f35d771",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "无",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
